package com.anlogic.sdk.openocd.ui;

import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import com.anlogic.sdk.openocd.Activator;
import com.anlogic.sdk.openocd.model.JtagCable;
import com.anlogic.sdk.openocd.model.JtagCableModel;
import com.anlogic.sdk.openocd.model.JtagDevice;
import com.anlogic.sdk.openocd.preferences.PersistentPreferences;
import com.anlogic.sdk.openocd.utils.OpenocdUtils;
import com.anlogic.sdk.utils.LogUtils;

public class MultiCableDevicesWidget {
	private static Logger logger = LogUtils.getLogger(MultiCableDevicesWidget.class);
	
	private Composite container;
	private Button autoDetectButton;
	private Button manualConfigButton;
	private Composite deviceTableComposite;
	private Composite autoDetectedComposite;
	private Composite manualConfigComposite;

	private StackLayout deviceTableLayout;
	private Tree autoDetectedTree;
	private TreeViewer autoDetectedViewer;
	private TableViewer manualConfigViewer;
	private Table manualConfigTable;
	
	private AutoDetectedCellModifier autoDetectedCellModifier;

	private JtagCable selectionCable;
	
	private JtagDevice selectionDevice;

	private Button refreshButton;
	
	private ToolItem addItem;

	private ToolItem delItem;

	private ToolItem moveUpItem;

	private ToolItem moveDownItem;

	private List<JtagCable> autoDetectedDevices = new ArrayList<JtagCable>();
	
	private List<JtagDevice> manualConfigDevices = new ArrayList<JtagDevice>();

	private String[] isFPGAItems = { "false", "true" };
	
	private PersistentPreferences fPersistentPreferences = null;
	
	private JtagCableModel model;

	public MultiCableDevicesWidget(Composite parent) {
		loadModel();
		this.createUI(parent);
	}

	public void loadModel() {
		model = new JtagCableModel();
		fPersistentPreferences = Activator.getInstance().getPersistentPreferences();
		String modelStr = fPersistentPreferences.getWorkspaceString(PersistentPreferences.JTAG_CABLE_MODEL, "");
		if (modelStr != null && !modelStr.isEmpty()) {
			model = model.readJsonString(modelStr);
		}
	}
	
	public Composite getContainer() {
		return this.container;
	}

	private void createUI(Composite parent) {
		container = new Composite(parent, SWT.DEFER);
		container.setLayout(new GridLayout(4, false));
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		GridLayoutFactory.fillDefaults().numColumns(2).margins(0, 0).applyTo(container);

		autoDetectButton = new Button(container, SWT.RADIO);
		autoDetectButton.setText("Automatically Discover Devices on JTAG Chain");
		autoDetectButton.setSelection(true);
		manualConfigButton = new Button(container, SWT.RADIO);
		manualConfigButton.setText("Manual Configuration of JTAG Chain");

		deviceTableComposite = new Composite((Composite) container, SWT.NULL);
		GridDataFactory.fillDefaults().span(2, 1).grab(true, true).applyTo(deviceTableComposite);
		GridLayoutFactory.fillDefaults().applyTo(deviceTableComposite);
		deviceTableLayout = new StackLayout();
		deviceTableComposite.setLayout((Layout) this.deviceTableLayout);

		createAutoDetectedViewer();
		createManualConfigViewer();
		
		setManualConfigDevices(model.getManualConfig());
		setAutoDetectedDevices(model.getAutoDetected());
		
		if (model.isAutoDetected()) {
			showAutoDetectedTable();
			if (!autoDetectedDevices.isEmpty() && model.getSelectionCable() != null) {
				selectAutoDetectedDevice(model.getSelectionCable());
			}
		} else {
			showManualConfigTable();
			if (!manualConfigDevices.isEmpty() && model.getManualSelectionDevice() != null) {
				selectManualConfigDevice(model.getManualSelectionDevice());
			}
		}

		addLinstener();
	}

	private void showAutoDetectedTable() {
		this.model.isAutoDetected(true);
		this.autoDetectButton.setSelection(true);
		this.manualConfigButton.setSelection(false);
		this.deviceTableLayout.topControl = autoDetectedComposite;
		this.deviceTableComposite.layout(true);
	}

	private void showManualConfigTable() {
		this.model.isAutoDetected(false);
		this.autoDetectButton.setSelection(false);
		this.manualConfigButton.setSelection(true);
		this.deviceTableLayout.topControl = manualConfigComposite;
		this.deviceTableComposite.layout(true);
		int idx = this.manualConfigTable.getSelectionIndex();
		enableUpDownControls(idx);
	}

	private void createAutoDetectedViewer() {
		autoDetectedComposite = new Composite(deviceTableComposite, SWT.NULL);
		GridDataFactory.fillDefaults().grab(true, true).applyTo(autoDetectedComposite);
		GridLayoutFactory.fillDefaults().applyTo(autoDetectedComposite);
		refreshButton = new Button(autoDetectedComposite, SWT.NONE);
		refreshButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
		refreshButton.setText("Refresh");
		autoDetectedTree = new Tree(autoDetectedComposite,
				SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE);
		autoDetectedViewer = new TreeViewer(autoDetectedTree);
		int[] bounds = { 300, 100, 100, 80, 100 };
		for (int i = 0; i < JtagCable.AUTO_DETECTED_PROPERTIES.length; i++) {
			TreeViewerColumn column = new TreeViewerColumn(autoDetectedViewer, SWT.FILL);
			column.getColumn().setText(JtagCable.AUTO_DETECTED_PROPERTIES[i]);
			column.getColumn().setWidth(bounds[i]);
			column.getColumn().setResizable(true);
			column.getColumn().setMoveable(false);
		}
		autoDetectedTree.setHeaderVisible(true);
		autoDetectedTree.setLinesVisible(true);
		autoDetectedTree.setLayout((Layout) new GridLayout(1, false));
		GridData td = new GridData(SWT.FILL, SWT.FILL, true, true);
		td.minimumHeight = 100;
		autoDetectedTree.setLayoutData(td);
		CellEditor[] editors = new CellEditor[5];
		editors[0] = new TextCellEditor(autoDetectedTree);
		editors[1] = new TextCellEditor(autoDetectedTree);
		editors[2] = new TextCellEditor(autoDetectedTree);
		editors[3] = new TextCellEditor(autoDetectedTree);
		editors[4] = new TextCellEditor(autoDetectedTree);
		autoDetectedViewer.setCellEditors(editors);
		autoDetectedViewer.setColumnProperties(JtagCable.AUTO_DETECTED_PROPERTIES);
		autoDetectedViewer.setContentProvider(new AutoDetectedContentProvider());
		autoDetectedViewer.setLabelProvider(new AutoDetectedLabelProvider());
		autoDetectedCellModifier = new AutoDetectedCellModifier(autoDetectedViewer);
		autoDetectedViewer.setCellModifier(autoDetectedCellModifier);
		autoDetectedViewer.setInput(new Object());
	}

	private void createManualConfigViewer() {
		manualConfigComposite = new Composite(deviceTableComposite, SWT.NULL);
		GridDataFactory.fillDefaults().grab(true, true).applyTo((Control) manualConfigComposite);
		GridLayoutFactory.fillDefaults().applyTo(manualConfigComposite);
		createToolBar();
		manualConfigTable = new Table(manualConfigComposite,
				SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE);
		manualConfigViewer = new TableViewer(manualConfigTable);
		int[] bounds = { 300, 100, 100, 80 };
		for (int i = 0; i < JtagCable.MANUAL_CONFIG_PROPERTIES.length; i++) {
			TableViewerColumn column = new TableViewerColumn(manualConfigViewer, SWT.FILL);
			column.getColumn().setText(JtagCable.MANUAL_CONFIG_PROPERTIES[i]);
			column.getColumn().setWidth(bounds[i]);
			column.getColumn().setResizable(true);
			column.getColumn().setMoveable(false);
		}
		manualConfigTable = manualConfigViewer.getTable();
		manualConfigTable.setHeaderVisible(true);
		manualConfigTable.setLinesVisible(true);
		manualConfigTable.setLayout((Layout) new GridLayout(1, false));
		GridData td = new GridData(4, 4, true, true);
		td.minimumHeight = 200;
		manualConfigTable.setLayoutData(td);
		CellEditor[] editors = new CellEditor[4];
		editors[0] = new TextCellEditor(manualConfigTable);
		editors[1] = new TextCellEditor(manualConfigTable);
		editors[2] = new TextCellEditor(manualConfigTable);
		ComboBoxCellEditor isFPGACombo = new ComboBoxCellEditor(manualConfigTable, isFPGAItems);
		editors[3] = isFPGACombo;
		manualConfigViewer.setCellEditors(editors);
		manualConfigViewer.setCellModifier(new JTAGChainCellModifier(manualConfigViewer));
		manualConfigViewer.setColumnProperties(JtagCable.MANUAL_CONFIG_PROPERTIES);
		manualConfigViewer.setContentProvider(new JTAGChainContentProvider());
		manualConfigViewer.setLabelProvider(new JTAGChainLabelProvider());
	}

	private void createToolBar() {
		ToolBar chainToolBar = new ToolBar(this.manualConfigComposite, SWT.FLAT | SWT.RIGHT | SWT.HORIZONTAL);
		chainToolBar.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
		this.addItem = new ToolItem(chainToolBar, SWT.PUSH);
		Image addImage = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/add.png").createImage();
		this.addItem.setImage(addImage);
		this.delItem = new ToolItem(chainToolBar, SWT.PUSH);
		Image delImage = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/delete.png").createImage();
		this.delItem.setImage(delImage);
		this.moveUpItem = new ToolItem(chainToolBar, SWT.PUSH);
		Image moveUpImage = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/up.png").createImage();
		this.moveUpItem.setImage(moveUpImage);
		this.moveDownItem = new ToolItem(chainToolBar, SWT.PUSH);
		Image moveDownImage = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/down.png").createImage();
		this.moveDownItem.setImage(moveDownImage);
	}

	private void addLinstener() {
		autoDetectButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				showAutoDetectedTable();
			}
		});

		manualConfigButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				showManualConfigTable();
			}
		});
		
		refreshButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				scanDevice();
				autoDetectedViewer.refresh();
			}
		});
		
		autoDetectedTree.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				TreeItem item = (TreeItem) e.item;
				if (item != null) {
					Object element = item.getData();
					if (element instanceof JtagDevice) {
						selectionCable = (JtagCable) item.getParentItem().getData();
						model.setSelectionCable(selectionCable);
						model.setSelectionDevice((JtagDevice)element);
					}
					if (element instanceof JtagCable) {
						selectionCable = (JtagCable) element;
						model.setSelectionCable(selectionCable);
					}
				}
			}
		});

		this.addItem.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				JtagDevice device = new JtagDevice("unknown", "0x0", "0", false);
				manualConfigDevices.add(device);
				manualConfigViewer.setInput(manualConfigDevices);
				manualConfigViewer.refresh();
			}
		});

		this.delItem.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int num = manualConfigTable.getItemCount();
				int idx = manualConfigTable.getSelectionIndex();
				ISelection selection = manualConfigViewer.getSelection();
				if (selection instanceof StructuredSelection) {
					StructuredSelection structuredSelection = (StructuredSelection) selection;
					Object firstElement = structuredSelection.getFirstElement();
					if (firstElement instanceof JtagDevice) {
						manualConfigDevices.remove(firstElement);
						manualConfigViewer.setInput(manualConfigDevices);
						if (idx == num - 1) {
							idx = idx - 1;
						}
						manualConfigTable.setSelection(idx);
						enableUpDownControls(idx);
						manualConfigViewer.refresh();
					}
				}
			}
		});

		this.manualConfigTable.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				TableItem item = (TableItem) e.item;
				if (item != null) {
					int idx = manualConfigTable.indexOf(item);
					enableUpDownControls(idx);
					model.setManualSelectionDevice((JtagDevice)item.getData());
				}
			}
		});

		this.moveDownItem.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				moveDeviceDownInChain();
			}
		});

		this.moveUpItem.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				moveDeviceUpInChain();
			}
		});
	}

	private void moveDeviceDownInChain() {
		int idx = this.manualConfigTable.getSelectionIndex();
		if (idx == this.manualConfigDevices.size() - 1)
			return;
		JtagDevice d = this.manualConfigDevices.get(idx);
		this.manualConfigDevices.remove(idx);
		this.manualConfigDevices.add(idx + 1, d);
		this.manualConfigViewer.refresh();
		enableUpDownControls(idx + 1);
	}

	private void moveDeviceUpInChain() {
		int idx = this.manualConfigTable.getSelectionIndex();
		if (idx == 0)
			return;
		JtagDevice d = this.manualConfigDevices.get(idx);
		this.manualConfigDevices.remove(idx);
		this.manualConfigDevices.add(idx - 1, d);
		this.manualConfigViewer.refresh();
		enableUpDownControls(idx - 1);
	}

	private void enableUpDownControls(int idx) {
		if (this.autoDetectButton.getSelection())
			return;
		if (idx == -1) {
			this.delItem.setEnabled(false);
			this.moveUpItem.setEnabled(false);
			this.moveDownItem.setEnabled(false);
		} else if (idx == 0 && this.manualConfigTable.getItemCount() == 1) {
			this.delItem.setEnabled(true);
			this.moveUpItem.setEnabled(false);
			this.moveDownItem.setEnabled(false);
		} else if (idx == 0) {
			this.delItem.setEnabled(true);
			this.moveUpItem.setEnabled(false);
			this.moveDownItem.setEnabled(true);
		} else if (idx == this.manualConfigTable.getItemCount() - 1) {
			this.delItem.setEnabled(true);
			this.moveUpItem.setEnabled(true);
			this.moveDownItem.setEnabled(false);
		} else {
			this.delItem.setEnabled(true);
			this.moveUpItem.setEnabled(true);
			this.moveDownItem.setEnabled(true);
		}
	}

	private class AutoDetectedContentProvider implements ITreeContentProvider {
		private AutoDetectedContentProvider() {
		}

		@Override
		public void dispose() {
		}

		@Override
		public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
		}

		@Override
		public Object[] getChildren(Object parent) {
			if (parent instanceof JtagCable) {
				return ((JtagCable) parent).getDevice().toArray();
			}
			return null;
		}

		@SuppressWarnings("unchecked")
		@Override
		public Object[] getElements(Object input) {
			if (input instanceof List)
				return ((List<JtagCable>) input).toArray();
			return new Object[0];
		}

		@Override
		public Object getParent(Object child) {
			return null;
		}

		@Override
		public boolean hasChildren(Object parent) {
			return parent instanceof JtagCable;
		}
	}

	private class AutoDetectedLabelProvider extends LabelProvider implements ITableLabelProvider {
		private AutoDetectedLabelProvider() {
		}

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int index) {
			if (element instanceof JtagCable) {
				JtagCable cable = (JtagCable) element;
				switch (index) {
				case 0:
					return cable.getName();
				case 4:
					return cable.getFrequency();
				}
			}
			if (element instanceof JtagDevice) {
				JtagDevice device = (JtagDevice) element;
				switch (index) {
				case 0:
					return device.getName();
				case 1:
					return device.getIdCode();
				case 2:
					return device.getIRLength();
				case 3:
					return device.isFPGA() ? "Yes" : "";
				}
			}
			return "";
		}
	}

	private class AutoDetectedCellModifier implements ICellModifier {
		private Viewer viewer;
		
		public AutoDetectedCellModifier(Viewer viewer) {
			this.viewer = viewer;
		}
		
		@Override
		public boolean canModify(Object element, String property) {
			if (element instanceof JtagCable) {
				if (JtagCable.FREQUENCE_PROPERTY.equals(property))
					return true;
			}
			return false;
		}

		@Override
		public Object getValue(Object element, String property) {
			if (element instanceof JtagCable) {
				JtagCable d = (JtagCable) element;
				if (JtagCable.FREQUENCE_PROPERTY.equals(property))
					return d.getFrequency();
			}
			return null;
		}

		@Override
		public void modify(Object element, String property, Object value) {
			if (element instanceof Item)
				element = ((Item) element).getData();
			if (element instanceof JtagCable) {
				JtagCable d = (JtagCable) element;
				if (JtagCable.FREQUENCE_PROPERTY.equals(property)) {
					if (checkForValidNumber((String)value) != -1L) {
						d.setFrequency((String) value);
					}
				}
			}
			this.viewer.refresh();
		}
	}

	private class JTAGChainCellModifier implements ICellModifier {
		private Viewer viewer;

		public JTAGChainCellModifier(Viewer viewer) {
			this.viewer = viewer;
		}

		@Override
		public boolean canModify(Object element, String property) {
			return true;
		}

		@Override
		public Object getValue(Object element, String property) {
			JtagDevice d = (JtagDevice) element;
			if (JtagCable.NAME_PROPERTY.equals(property))
				return d.getName();
			if (JtagCable.IDCODE_PROPERTY.equals(property))
				return d.getIdCode();
			if (JtagCable.IRLENGTH_PROPERTY.equals(property))
				return d.getIRLength();
			if (JtagCable.ISFPGA_PROPERTY.equals(property)) {
				return d.isFPGA() ? 1 : 0;
			}
			return null;
		}

		@Override
		public void modify(Object element, String property, Object value) {
			if (element instanceof Item)
				element = ((Item) element).getData();
			JtagDevice d = (JtagDevice) element;
			if (JtagCable.NAME_PROPERTY.equals(property)) {
				d.setName((String) value);
			}
			if (JtagCable.IDCODE_PROPERTY.equals(property)) {
				try {
					Long i = Long.decode((String) value);
					d.setIdCode("0x" + Long.toHexString(i.longValue()));
				} catch (NumberFormatException numberFormatException) {
				}
			}
			if (JtagCable.IRLENGTH_PROPERTY.equals(property)) {
				try {
					Long i = Long.decode((String) value);
					d.setIRLength(Long.toString(i.longValue()));
				} catch (NumberFormatException numberFormatException) {
				}
			}
			if (JtagCable.ISFPGA_PROPERTY.equals(property)) {
				int idx = (Integer) value;
				if (idx < 0) {
					idx = 0;
				}
				String isFPGA = isFPGAItems[idx];
				d.setFPGA(isFPGA.equals("true"));
			}
			this.viewer.refresh();
		}
	}

	private class JTAGChainContentProvider implements IStructuredContentProvider {
		@SuppressWarnings("unchecked")
		@Override
		public Object[] getElements(Object input) {
			if (input instanceof List)
				return ((List<JtagDevice>) input).toArray();
			return null;
		}

		@Override
		public void dispose() {
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private class JTAGChainLabelProvider extends LabelProvider implements ITableLabelProvider {
		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int index) {
			if (!(element instanceof JtagDevice))
				return "";
			JtagDevice d = (JtagDevice) element;
			switch (index) {
			case 0:
				return d.getName();
			case 1:
				return d.getIdCode();
			case 2:
				return d.getIRLength();
			case 3:
				return d.isFPGA() ? "true" : "false";
			}
			return "";
		}
	}
	
	private long checkForValidNumber(String str) {
		if (str == null || str.isEmpty())
			return -1L;
		try {
			if (str.startsWith("0x"))
				return Long.parseLong(str.substring(2), 16);
			return Long.parseLong(str);
		} catch (Exception exception) {
			return -1L;
		}
	}
	
	public void setAutoDetectedDevices(List<JtagCable> devices) {
		autoDetectedViewer.setInput(devices);
		autoDetectedViewer.expandAll();
		autoDetectedDevices = devices;
	}
	
	public void setManualConfigDevices(List<JtagDevice> devices) {
		manualConfigViewer.setInput(devices);
		manualConfigDevices = devices;
	}

	public void selectAutoDetectedDevice(JtagCable cable) {
		if (cable != null) {
			for (TreeItem item : autoDetectedTree.getItems()) {
				JtagCable temp = (JtagCable) item.getData();
				if (temp.getName().equals(cable.getName())) {
					autoDetectedTree.select(item);
					autoDetectedTree.setSelection(item);
					selectionCable = cable;
					model.setSelectionCable(selectionCable);
					break;
				}
			}
		}
	}
	
	public void selectAutoDetectedDevice(JtagCable cable, JtagDevice device) {
		if (cable != null && device != null) {
			for (TreeItem item : autoDetectedTree.getItems()) {
				JtagCable temp = (JtagCable) item.getData();
				if (temp.getName().equals(cable.getName())) {
					selectionCable = cable;
					model.setSelectionCable(selectionCable);
					for (TreeItem it : item.getItems()) {
						autoDetectedTree.select(it);
						JtagDevice dev = (JtagDevice) it.getData();
						if (dev.getName().equals(device.getName()) ) {
							autoDetectedTree.setSelection(it);
							selectionDevice = device;
							model.setSelectionDevice(selectionDevice);
							break;
						}
					}
					break;
				}
			}
		}
	}
	
	public void selectManualConfigDevice(JtagDevice device) {
		if (device != null) {
			for (TableItem item : manualConfigTable.getItems()) {
				JtagDevice cable = (JtagDevice) item.getData();
				if (device.getName().equals(cable.getName())) {
					manualConfigTable.setSelection(item);
					break;
				}
			}
		}
	}
	
	public JtagCable getSelecionCable() {
		return selectionCable;
	}
	
	public JtagDevice getSelecionDevice() {
		return selectionDevice;
	}
	
	public void scanDevice() {
		Job job = new Job(String.format("%s executing...", "Scan Usb")) {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				logger.info("Scan Usb...");
				OpenocdUtils.killExecute("openocd");
				List<JtagCable> devices = OpenocdUtils.scanUsb(JtagCable.VID, JtagCable.PID);
				Display.getDefault().asyncExec(new Runnable() {
					@Override
					public void run() {
						setAutoDetectedDevices(devices);
						selectAutoDetectedDevice(devices.get(0));
						autoDetectedViewer.refresh();
					}
				});
				logger.info("Scan Usb done.");
				return Status.OK_STATUS;
			}
		};
		job.setUser(true);
		job.schedule();
	}
	
	public void savePreferences() {
		model.setAutoDetected(autoDetectedDevices);
		model.setManualConfig(manualConfigDevices);
		fPersistentPreferences.putWorkspaceString(PersistentPreferences.JTAG_CABLE_MODEL, model.toJsonString());
		fPersistentPreferences.flush();
	}
}
